package com.coolw.dynamic.thread.pool.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.coolw.common.api.PageResponse;
import com.coolw.dynamic.thread.pool.context.DynamicThreadPoolManager;
import com.coolw.dynamic.thread.pool.domain.dto.ThreadPoolStatDTO;
import com.coolw.dynamic.thread.pool.domain.request.ThreadPoolStatPageRequest;
import com.coolw.dynamic.thread.pool.entity.ThreadPoolConfigEntity;
import com.coolw.dynamic.thread.pool.entity.ThreadPoolStatEntity;
import com.coolw.dynamic.thread.pool.mapper.ThreadPoolStatMapper;
import com.coolw.dynamic.thread.pool.service.ThreadPoolConfigService;
import com.coolw.dynamic.thread.pool.service.ThreadPoolStatService;
import com.coolw.dynamic.thread.pool.util.MybatisPlusUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.bean.BeanUtil;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.data.id.IdUtil;
import org.dromara.hutool.core.date.DateFormatPool;
import org.dromara.hutool.core.date.DateUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 线程池统计信息Service实现类
 *
 * @author coolw
 * @date 2024/5/17 15:21
 */
@Slf4j
@Service
public class ThreadPoolStatServiceImpl extends ServiceImpl<ThreadPoolStatMapper, ThreadPoolStatEntity>
        implements ThreadPoolStatService {

    @Autowired
    private ThreadPoolConfigService threadPoolConfigService;

    @Override
    public PageResponse<ThreadPoolStatDTO> pageList(ThreadPoolStatPageRequest request) {
        String poolCode = request.getPoolCode();
        String poolName = request.getPoolName();
        // 分页条件
        LambdaQueryWrapper<ThreadPoolStatEntity> queryWrapper = Wrappers.<ThreadPoolStatEntity>lambdaQuery()
                .eq(StrUtil.isNotBlank(poolCode), ThreadPoolStatEntity::getPoolCode, poolCode)
                .likeRight(StrUtil.isNotBlank(poolName), ThreadPoolStatEntity::getPoolName, poolName)
                .orderByDesc(ThreadPoolStatEntity::getId);
        Page<ThreadPoolStatEntity> page = Page.of(request.getPageNum(), request.getPageSize());

        // 分页结果
        Page<ThreadPoolStatEntity> pageSource = page(page, queryWrapper);

        // 结果转换
        return MybatisPlusUtil.toPage(pageSource, ThreadPoolStatDTO.class);
    }

    @Override
    public ThreadPoolStatDTO execute() {
        List<String> poolCodes = DynamicThreadPoolManager.getKeys();
        if (CollUtil.isEmpty(poolCodes)) {
            return new ThreadPoolStatDTO("线程池缓存信息为空,本次不统计");
        }

        List<ThreadPoolConfigEntity> configList = threadPoolConfigService.listByPoolCodes(poolCodes);
        if (CollUtil.isEmpty(configList)) {
            log.info("线程池配置信息不存在,本次不统计,poolCodes:{}", poolCodes);
            return new ThreadPoolStatDTO("线程池配置信息不存在,本次不统计");
        }

        ThreadPoolStatDTO statDTO = DynamicThreadPoolManager.getInstance().monitor(configList);
        // 保存线程池统计信息
        List<ThreadPoolStatEntity> statEntityList = convert(statDTO);
        if (CollUtil.isNotEmpty(statEntityList)) {
            saveBatch(statEntityList);
        }

        statDTO.setMessage("线程池统计完成");
        return statDTO;
    }

    private List<ThreadPoolStatEntity> convert(ThreadPoolStatDTO statDTO) {
        if (Objects.isNull(statDTO)) {
            return Collections.emptyList();
        }
        List<ThreadPoolStatDTO.StatInfo> statInfoList = statDTO.getStatInfoList();
        if (CollUtil.isEmpty(statInfoList)) {
            return Collections.emptyList();
        }

        String batchNo = IdUtil.getSnowflakeNextIdStr();
        Date statStartTime = DateUtil.parse(statDTO.getStartTime(), DateFormatPool.NORM_DATETIME_PATTERN);
        Date statEndTime = DateUtil.parse(statDTO.getEndTime(), DateFormatPool.NORM_DATETIME_PATTERN);
        List<ThreadPoolStatEntity> statEntityList = new ArrayList<>(statInfoList.size());
        statInfoList.forEach(s -> {
            ThreadPoolStatEntity entity = BeanUtil.copyProperties(s, ThreadPoolStatEntity.class);
            entity.setStatNo(IdUtil.getSnowflakeNextIdStr());
            entity.setBatchNo(batchNo);
            entity.setStatStartTime(statStartTime);
            entity.setStatEndTime(statEndTime);
            statEntityList.add(entity);
        });
        return statEntityList;
    }
}
